import os, sys, string, re, time
import urllib
import csv
import xml.dom.minidom


from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.api import urlfetch
from google.appengine.ext.webapp import template


class YahooQuoteProvider:
	def __init__(self):
		pass
	def getlastprice(self, symbol):
		pass
		
	def getlastvolume(self, symbol):
		pass
	
	def getpricedataasencodedforgooglecharts(self, symbol, startdate, stopdate):
		pass
		
	def getvolumedataasencodedforgooglecharts(self, symbol, startdate, stopdate):
		pass
		
	def getGoogleChartsLink(d1, d2, symbol):
		quotes=getQuotes(d1,d2,symbol)
		quotes.reverse()
		data = ','.join(map(lambda (quote):quote[4], quotes))
		maxprice = max(map(lambda (quote):float(quote[4]), quotes))*1.05
		url = 'http://chart.apis.google.com/chart?'
		query = (
		('chs','600x400'),
		('chd','t:'+data),
		('chds', '0,%d'%maxprice),
		('cht','lc'),
		('chl',symbol),)
		query = '&'.join(map(lambda (var, val): '%s=%s' % (var, str(val)), query))
		return url + query
		
	def getGoogleChartsCandlestickLink(d1, d2, symbol):
		quotes=getQuotes(d1,d2,symbol)
		quotes.reverse()
		data = ','.join(map(lambda (quote):quote[4], quotes))
		maxprice = max(map(lambda (quote):float(quote[4]), quotes))*1.05
		url = 'http://chart.apis.google.com/chart?'
		query = (
		('chs','600x400'),
		('chd','t:'+data),
		('chds', '0,%d'%maxprice),
		('cht','lc'),
		('chl',symbol),)
		query = '&'.join(map(lambda (var, val): '%s=%s' % (var, str(val)), query))
		return url + query
		
		
def splitLines(buf):
	def removeCarriage(s):
		if s[-1]=='\r': return s[:-1]
		else: return s
	return map(removeCarriage,filter(lambda x:x, string.split(buf, '\n')))	
	
	
def getCSVLink(d1, d2, symbol):
	url='http://ichart.finance.yahoo.com/table.csv'
	query = (
	('a', '%02d' % (int(d1[1])-1)),
	('b', d1[2]),
	('c', d1[0]),
	('d', '%02d' % (int(d2[1])-1)),
	('e', d2[2]),
	('f', d2[0]),
	('s', symbol),
	('y', '0'),
	('g', 'd'),
	('ignore', '.csv'),)
	query = '&'.join(map(lambda (var, val): '%s=%s' % (var, str(val)), query))
	print url+'?'+query
	return url+'?'+query
	

def getQuotes(d1, d2, symbol):
	f=urlfetch.fetch(getCSVLink(d1,d2,symbol)).content
	lines=splitLines(f)
	if re.match('no prices', lines[0], re.I): return
	lines,result=lines[1:],[]
	for l in lines:
		l=l.split(',')
		result.append([symbol,l[0].replace('-','')]+l[1:])
	return result
		
def getSplits(symbol):
	url = 'http://finance.yahoo.com/q/bc?s=%s&t=my' % symbol
	html=urlfetch.fetch(url).content
	#html = f.read()
	start = html.find('<center>Splits:')
	end = html.find('</center>', start)
	splitshtml = html[start+len('<center>Splits:'):end]
	splitsunformatteddate =[x for x in map(lambda(i): [time.strptime(i[0], '%d-%b-%y'), int(i[1].strip('[]').split(':')[0]), int(i[1].strip('[]').split(':')[1])], map(lambda (s): s.split(' '), splitshtml.replace('<nobr>', '').replace('</nobr>', '').split(', '))) if x[0][0]<2012]
	splitsformatteddate = map(lambda (i): ['%d%02d%02d'%(i[0][0],i[0][1],i[0][2]), i[1], i[2]], splitsunformatteddate)
	return splitsformatteddate 

def applySplits(quotes, splits):
	for quote in quotes:
		for split in splits:
			if quote[1]<split[0]:
				ratio = float(split[2])/float(split[1])
				quote[2]=str(float(quote[2])*ratio)
				quote[3]=str(float(quote[3])*ratio)
				quote[4]=str(float(quote[4])*ratio)
				quote[5]=str(float(quote[5])*ratio)
	return quotes
	
def getPriceLines(maxprice):
	maxprice = int(maxprice)
	if len(range(0,maxprice,1)) < 6:
		return range(0,maxprice+1,1)
	elif len(range(0,maxprice,2)) < 6:
		return range(0,maxprice+1,2)
	elif len(range(0,maxprice,5)) < 8:
		return range(0,maxprice+1,5)
	elif len(range(0,maxprice,10)) < 8:
		return range(0,maxprice+1,10)
	elif len(range(0,maxprice,20)) < 6:
		return range(0,maxprice+1,20)
	elif len(range(0,maxprice,25)) < 6:
		return range(0,maxprice+1,25)
	elif len(range(0,maxprice,50)) < 6:
		return range(0,maxprice+1,50)
	else:
		return map(lambda(x):x*100, getPriceLines(maxprice/100))
	
def createSVGCandlestickChart(d1, d2, symbol, size=(600,400)):
	quotes=applySplits(getQuotes(d1,d2,symbol), getSplits(symbol))
	quotes.reverse()
	#data = ','.join(map(lambda (quote):quote[4], quotes))
	maxprice = max(map(lambda (quote):float(quote[4]), quotes))*1.10
	maxvolume = max(map(lambda (quote):float(quote[6]), quotes))*1.10
	width,height = size
	leftmargin = 40
	rightmargin = 20
	topmargin = 20
	bottommargin = 20
	leftpadding = 10
	candlewidth = 0.8 * (width-leftmargin-rightmargin)/len(quotes)
	candlespacing = 0.2 * (width-leftmargin-rightmargin)/len(quotes)
	
	svgtemplate = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
	<svg
	   xmlns:svg="http://www.w3.org/2000/svg"
	   xmlns="http://www.w3.org/2000/svg"
	   version="1.0"
	   id="chart">
	  <defs
	     id="defs" />
	</svg>"""
	
	svgdom = xml.dom.minidom.parseString(svgtemplate)
	
	#set size
	svgdom.documentElement.attributes['width'] = str(width)
	svgdom.documentElement.attributes['height'] = str(height)
	
	#draw someaxes
	xaxis = svgdom.documentElement.appendChild(svgdom.createElement('path'))
	xaxis.attributes['d'] = 'M %d,%d L %d,%d' % (leftmargin, height-bottommargin, width-rightmargin, height-bottommargin)
	xaxis.attributes['style'] = 'fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
	
	yaxis = svgdom.documentElement.appendChild(svgdom.createElement('path'))
	yaxis.attributes['d'] = 'M %d,%d L %d,%d' % (leftmargin, height-bottommargin, leftmargin, topmargin)
	yaxis.attributes['style'] = 'fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
	
	#draw a title
	titletext = svgdom.documentElement.appendChild(svgdom.createElement('text'))
	titletext.appendChild(svgdom.createTextNode(quotes[0][0]))
	titletext.attributes['x'] = '%d' % (width/2)
	titletext.attributes['y'] = '%d' % ( 14 )
	titletext.attributes['font-size'] = '%d' % (16)
	titletext.attributes['text-anchor'] = 'middle'
	titletext.attributes['font-family'] = 'arial, "lucida console", sans-serif'
	
	
	#draw some horizonal bars for price
	pricelines = getPriceLines(maxprice)[1:]
	
	i=1
	markertomarkerdistance = (height-topmargin-bottommargin)/len(pricelines)
	for priceline in pricelines:
		#markery=height-bottommargin - markertomarkerdistance * i
		markery = height - bottommargin - (priceline/maxprice * ( height-bottommargin-topmargin))
		pricemarker = svgdom.documentElement.appendChild(svgdom.createElement('path'))
		pricemarker.attributes['d'] = 'M %d,%d L %d,%d' % (leftmargin,markery, width-rightmargin, markery)
		pricemarker.attributes['style'] = 'fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
		
		pricetextmarker = svgdom.documentElement.appendChild(svgdom.createElement('text'))
		pricetextmarker.appendChild(svgdom.createTextNode(str(priceline)))
		pricetextmarker.attributes['x'] = '%d' % (leftmargin-4)
		pricetextmarker.attributes['y'] = '%d' % ( markery+5 )
		pricetextmarker.attributes['font-size'] = '%d' % (12)
		pricetextmarker.attributes['text-anchor'] = 'end'
		pricetextmarker.attributes['font-family'] = 'arial, "lucida console", sans-serif'
		
		i+=1
	
	
	# draw some wicks and tails and draw some candle bodies
	i = 0
	candletocandledistance = (width-leftmargin-rightmargin)/len(quotes)
	candlewidth = 0.25 * candletocandledistance
	candlespacing = 0.2 * candletocandledistance
	
	volumewidth = candlewidth
	
	month =  int(quotes[0][1][4:6])
	if int(quotes[0][1][6:9])<4:
		month-=1 
	for quote in quotes:
		#date markers first
		if int(quote[1][4:6])!=month:
			markerx=candletocandledistance * i + candlewidth/2 + leftmargin + 0.25 +leftpadding
			monthmarker = svgdom.documentElement.appendChild(svgdom.createElement('path'))
			monthmarker.attributes['d'] = 'M %d,%d L %d,%d' % (markerx, height-bottommargin, markerx, topmargin)
			monthmarker.attributes['style'] = 'fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
			
			monthtextmarker = svgdom.documentElement.appendChild(svgdom.createElement('text'))
			monthtextmarker.appendChild(svgdom.createTextNode(time.strftime('%b%d', time.strptime(quote[1], '%Y%m%d'))))
			monthtextmarker.attributes['x'] = '%d' % (markerx)
			monthtextmarker.attributes['y'] = '%d' % ( height-4)
			monthtextmarker.attributes['font-size'] = '%d' % (12)
			monthtextmarker.attributes['text-anchor'] = 'middle'
			monthtextmarker.attributes['font-family'] = 'arial, "lucida console", sans-serif'
			
			month =  int(quote[1][4:6]) 
			
		#volume bar next
		volume = int(quote[6])
		volumetop =  height - bottommargin - (volume/maxvolume) * (height-bottommargin-topmargin) *  0.30
		volumeheight=abs(height-bottommargin-volumetop)
		volumex = candletocandledistance * i + leftmargin +leftpadding
		
		volumemarker = svgdom.documentElement.appendChild(svgdom.createElement('rect'))
		volumemarker.attributes['width'] = str(volumewidth)
		volumemarker.attributes['height'] = str(volumeheight)
		volumemarker.attributes['volume'] = quote[6]
		volumemarker.attributes['x'] = str(volumex)
		volumemarker.attributes['y'] = str(volumetop)
		volumemarker.attributes['style'] = 'fill:#6688aa;fill-opacity:1;fill-rule:nonzero;stroke:#6688aa;stroke-width:0.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.19999981;stroke-dasharray:none;stroke-opacity:1'
			
		
		
		#wicks after that
		high = float(quote[3])
		low = float(quote[4])
		
		wickx = candletocandledistance * i + candlewidth/2 + leftmargin + 0.25 +leftpadding
		wickylow = height - bottommargin - (low/maxprice * ( height-bottommargin-topmargin))
		wickyhigh = height - bottommargin - (high/maxprice * (height-bottommargin-topmargin))
		
		
		wick = svgdom.documentElement.appendChild(svgdom.createElement('path'))
		wick.attributes['d'] = 'M %d,%d L %d,%d' % (wickx, wickylow, wickx,wickyhigh)
		wick.attributes['style'] = 'fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'
		
		open = float(quote[2])
		close = float(quote[5])
		
		#candlebody
		candleopen =  height - bottommargin - (open/maxprice * (height-bottommargin-topmargin))
		candleclose =  height - bottommargin - (close/maxprice * (height-bottommargin-topmargin))
		candleheight=abs(candleopen-candleclose)
		candlex = candletocandledistance * i + leftmargin +leftpadding
		
		candle = svgdom.documentElement.appendChild(svgdom.createElement('rect'))
		candle.attributes['width'] = str(candlewidth)
		candle.attributes['height'] = str(candleheight)
		#candle.attributes['open'] = str(candleheight)
		#candle.attributes['close'] = str(candleheight)
		candle.attributes['x'] = str(candlex)
		candle.attributes['y'] = str(min([candleopen, candleclose]))
		if candleopen < candleclose:
			candle.attributes['width'] = str(candlewidth)
			candle.attributes['style'] = 'fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.20000005;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.19999981;stroke-dasharray:none;stroke-opacity:1'
		else:
			candle.attributes['width'] = str(candlewidth*1.8)
			candle.attributes['style'] = 'fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4.19999981;stroke-dasharray:none;stroke-opacity:1'
					
		i+=1
	
	return svgdom.toxml()
		
		
		
		
		
		
		
	